/*
 * @Author: dengzhijun 1726768643@qq.com
 * @Date: 2025-01-18 17:13:42
 * @LastEditors: dengzhijun 1726768643@qq.com
 * @LastEditTime: 2025-01-20 15:06:17
 * @FilePath: /Tools/Test/include/gtest.h
 * @Description: 
 * Copyright (c) 2025 by ${dengzhijun} email: ${1726768643@qq.com}, All Rights Reserved.
 */
#ifndef G_TEST_H
#define G_TEST_H

#include <iostream>
#include <vector>
#include <string>
#include <functional>

// ANSI 转义序列
#define COLOR_GREEN "\033[32m"
#define COLOR_RED "\033[31m"
#define COLOR_RESET "\033[0m"

// 测试用例类

class TestCase
{
public:
    TestCase(const std::string& name, std::function<void()> testFunc)
        : name(name)
        , testFunc(testFunc)
    {

    }
    void Run()
    {
        try
        {
            testFunc();
            std::cout << COLOR_GREEN << "[PASS] " << COLOR_RESET << name << std::endl;
        }
        catch (const std::exception& e)
        {
            std::cout << COLOR_RED << "[FAIL] " << COLOR_RESET << name << " - " << e.what() << std::endl;
        }
    }

private:
    std::string name;
    std::function<void()> testFunc;
};

// 测试套件类
class TestSuite
{
public:
    static TestSuite& GetInstance()
    {
        static TestSuite instance;
        return instance;
    }

    void AddTestCase(const std::string& name, std::function<void()> testFunc)
    {
        testCases.emplace_back(name, testFunc);
    }
    void Run()
    {
        std::cout << "测试个数； " << testCases.size() << std::endl;
        for (auto& testCase : testCases)
        {
            testCase.Run();
        }
    }
private:
    TestSuite() = default;
    ~TestSuite() = default;
    std::vector<TestCase> testCases;
};


#define TEST(testSuite, testName) \
void testSuite##testName(); \
    struct testSuite##testName##Register { \
        testSuite##testName##Register() { \
        TestSuite::GetInstance().AddTestCase(#testSuite "." #testName, testSuite##testName); \
    } \
} testSuite##testName##Instance; \
    void testSuite##testName()

#define EXPECT_EQ(a, b) \
    if ((a) == (b)) { \
        throw std::runtime_error("Expected " #a " != " #b " but they are equal at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_NE(a, b) \
    if ((a) == (b)) { \
        throw std::runtime_error("Expected " #a " != " #b " but they are equal at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_GT(a, b) \
    if ((a) <= (b)) { \
        throw std::runtime_error("Expected " #a " > " #b " at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_LT(a, b) \
    if ((a) >= (b)) { \
        throw std::runtime_error("Expected " #a " < " #b " at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_GE(a, b) \
    if ((a) < (b)) { \
        throw std::runtime_error("Expected " #a " >= " #b " at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_LE(a, b) \
    if ((a) > (b)) { \
        throw std::runtime_error("Expected " #a " <= " #b " at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_STREQ(a, b) \
    if (std::string(a) != std::string(b)) { \
        throw std::runtime_error("Expected " #a " == " #b ", but got: " + std::string(a) + " vs " + std::string(b) + " at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_STRNE(a, b) \
    if (std::string(a) == std::string(b)) { \
        throw std::runtime_error("Expected " #a " != " #b " but they are equal at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_FLOAT_EQ(a, b) \
    if (std::abs((a) - (b)) > 1e-6) { \
        throw std::runtime_error("Expected " #a " (~" + std::to_string(a) + ") to be approximately equal to " #b " (" + std::to_string(b) + ") at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_DOUBLE_EQ(a, b) \
    if (std::abs((a) - (b)) > 1e-9) { \
        throw std::runtime_error("Expected " #a " (~" + std::to_string(a) + ") to be approximately equal to " #b " (" + std::to_string(b) + ") at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_FALSE(a) \
    if ((a) != false) { \
        throw std::runtime_error("Expected " #a " to be false at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define EXPECT_TRUE(a) \
    if ((a) != true) { \
        throw std::runtime_error("Expected " #a " to be false at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define ASSERT_NULL(a) \
    if ((a) != nullptr) { \
        throw std::runtime_error("Expected " #a " to be null at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#define ASSERT_NOT_NULL(a) \
    if ((a) == nullptr) { \
        throw std::runtime_error("Expected " #a " to be not null at " __FILE__ ":" + std::to_string(__LINE__)); \
    }

#endif // GTEST_H
